﻿using ClosedXML.Excel;
using System.ComponentModel;
using System.Reflection;
using System.Text;

namespace QMERP.Infrastructure.Extensions
{
    public static class ListExtension
    {
        /// <summary>
        /// List转为Excel
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static MemoryStream ToExcel<T>(this List<T> list) where T : class
        {
            var workbook = new XLWorkbook();
            var sheet = workbook.AddWorksheet();
            var headerRow = sheet.Row(1);
            Type objType = typeof(T);
            var propInfos = objType.GetProperties();
            //取属性上的自定义特性
            int c = 0;
            foreach (PropertyInfo propInfo in propInfos)
            {
                object[] objAttrs = propInfo.GetCustomAttributes(typeof(DescriptionAttribute), true);
                if (objAttrs.Length > 0)
                {
                    DescriptionAttribute? attr = objAttrs[0] as DescriptionAttribute;
                    if (attr != null)
                    {
                        headerRow.Cell(c).SetValue(attr.Description);
                        c++;
                    }
                }
            }
            for (int i = 0; i < list.Count(); i++)
            {
                var item = list[i];
                var row = sheet.Row(i + 1);
                int j = 0;
                foreach (PropertyInfo propInfo in propInfos)
                {
                    object[] objAttrs = propInfo.GetCustomAttributes(typeof(DescriptionAttribute), true);
                    if (objAttrs.Length > 0)
                    {
                        DescriptionAttribute? attr = objAttrs[0] as DescriptionAttribute;
                        if (attr != null)
                        {
                            object? value = propInfo.GetValue(list[i], null);
                            string obj = value == null ? "" : value.ToString()!;
                            var cell = row.Cell(j);
                            if (obj == "")
                            {
                                cell.SetValue(obj);
                            }
                            else
                            {
                                string? type = propInfo.PropertyType.FullName;
                                if (type == null || type.Contains("System.String"))
                                {
                                    cell.SetValue(obj);
                                }
                                else if (type.Contains("System.DateTime"))
                                {
                                    DateTime.TryParse(obj, out DateTime dateV);
                                    cell.SetValue(dateV.ToString("yyyy/MM/dd HH:mm:ss"));
                                }
                                else if (type.Contains("System.Boolean"))
                                {
                                    bool.TryParse(obj, out bool boolV);
                                    cell.SetValue(boolV);
                                }
                                else if (type.Contains("System.Int") || type.Contains("System.Byte"))
                                {
                                    int.TryParse(obj, out int intV);
                                    cell.SetValue(intV);
                                }
                                else if (type.Contains("System.Decimal") || type.Contains("System.Double"))
                                {
                                    double.TryParse(obj, out double doubV);
                                    cell.SetValue(doubV);
                                }
                                else
                                {
                                    cell.SetValue("");
                                }
                            }
                            j++;
                        }
                    }
                }
            }
            for (int columnNum = 1; columnNum <= headerRow.LastCellUsed().Address.ColumnNumber; columnNum++)
            {
                double columnWidth = sheet.Column(columnNum).Width / 256;
                for (int rowNum = 1; rowNum <= sheet.LastRowUsed().RowNumber(); rowNum++)
                {
                    IXLRow currentRow;
                    //当前行未被使用过  
                    if (sheet.Row(rowNum) == null)
                    {
                        currentRow = sheet.Row(rowNum);
                    }
                    else
                    {
                        currentRow = sheet.Row(rowNum);
                    }

                    if (currentRow.Cell(columnNum) != null)
                    {
                        var currentCell = currentRow.Cell(columnNum);
                        int length = Encoding.Default.GetBytes(currentCell.ToString() ?? "").Length;
                        if (columnWidth < length)
                        {
                            columnWidth = length;
                        }
                    }
                }
                sheet.Column(columnNum).Width = (columnWidth + 5) * 256;
            }
            MemoryStream ms = new();

            workbook.SaveAs(ms);
            workbook.Dispose();
            ms.Flush();
            ms.Position = 0;
            return ms;
        }
    }
}
